using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Book.Blog.Core.DTOs;
using Book.Blog.Core.Entities;
using Book.Blog.Core.Interfaces;
using Book.Blog.Infrastructure.Data;
using Nest;

namespace Book.Blog.Infrastructure.Services
{
    public class SearchService : ISearchService
    {
        private readonly BlogDbContext _context;
        private readonly IElasticClient _elasticClient;

        public SearchService(BlogDbContext context, IElasticClient elasticClient)
        {
            _context = context;
            _elasticClient = elasticClient;
        }

        public async Task<SearchResultDTO> SearchAsync(SearchRequestDTO request)
        {
            var query = _context.Posts
                .Include(p => p.Author)
                .Include(p => p.Category)
                .Include(p => p.Tags)
                .Where(p => p.IsPublished && !p.IsDeleted);

            if (!string.IsNullOrEmpty(request.Query))
            {
                query = query.Where(p => 
                    p.Title.Contains(request.Query) || 
                    p.Content.Contains(request.Query) ||
                    p.Summary.Contains(request.Query));
            }

            if (request.CategoryId.HasValue)
            {
                query = query.Where(p => p.CategoryId == request.CategoryId);
            }

            if (request.TagIds?.Any() == true)
            {
                query = query.Where(p => p.Tags.Any(t => request.TagIds.Contains(t.Id)));
            }

            if (request.AuthorId.HasValue)
            {
                query = query.Where(p => p.AuthorId == request.AuthorId);
            }

            if (request.FromDate.HasValue)
            {
                query = query.Where(p => p.CreatedAt >= request.FromDate);
            }

            if (request.ToDate.HasValue)
            {
                query = query.Where(p => p.CreatedAt <= request.ToDate);
            }

            var totalCount = await query.CountAsync();
            var posts = await query
                .Skip(request.Skip)
                .Take(request.Take)
                .ToListAsync();

            var items = posts.Select(p => new SearchItemDTO
            {
                Id = p.Id,
                Title = p.Title,
                Content = p.Content,
                CreatedAt = p.CreatedAt,
                UpdatedAt = p.UpdatedAt,
                Score = 1.0,
                TagNames = p.Tags.Select(t => t.Name).ToList()
            }).ToList();

            return new SearchResultDTO
            {
                TotalCount = totalCount,
                Items = items
            };
        }

        public async Task<bool> IndexPostAsync(Post post)
        {
            var response = await _elasticClient.IndexDocumentAsync(post);
            return response.IsValid;
        }

        public async Task<bool> UpdatePostIndexAsync(Post post)
        {
            var response = await _elasticClient.UpdateAsync<Post>(post.Id, u => u
                .Doc(post)
                .DocAsUpsert());
            return response.IsValid;
        }

        public async Task<bool> DeletePostIndexAsync(Guid postId)
        {
            var response = await _elasticClient.DeleteAsync<Post>(postId);
            return response.IsValid;
        }

        public async Task<bool> ReindexAllAsync()
        {
            var posts = await _context.Posts
                .Include(p => p.Author)
                .Include(p => p.Category)
                .Include(p => p.Tags)
                .Where(p => p.IsPublished && !p.IsDeleted)
                .ToListAsync();

            var response = await _elasticClient.BulkAsync(b => b
                .Index("posts")
                .IndexMany(posts));

            return response.IsValid;
        }
    }
} 